home *** CD-ROM | disk | FTP | other *** search
/ Die Speccy' 97 / Die Speccy' 97.iso / amiga_system / the_aminet / comm / tcp / mufs_telnetd.lha / telnetd2_0.lha / telnetd-2.0 / source / telnetd.c < prev    next >
C/C++ Source or Header  |  1995-04-13  |  66KB  |  1,591 lines

  1. /*
  2.  *      $Filename: telnetd.c $
  3.  *      $Revision: 2.0 $
  4.  *      $Date: 1995/04/13 19:53:48 $
  5.  *
  6.  *      Copyright (C) 1993,94 by Steve Holland <sdh4@cornell.edu>
  7.  *      Copyright (C) 1995 by Peter Simons <simons@peti.rhein.de>
  8.  *
  9.  *      This program is free software; you can redistribute it and/or
  10.  *      modify it under the terms of the GNU General Public License as
  11.  *      published by the Free Software Foundation; either version 2 of
  12.  *      the License, or (at your option) any later version.
  13.  *
  14.  *      This program is distributed in the hope that it will be useful,
  15.  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17.  *      General Public License for more details.
  18.  *
  19.  *      You should have received a copy of the GNU General Public License
  20.  *      along with this program; if not, write to the Free Software
  21.  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22.  *
  23.  *      $Id: telnetd.c 2.0 1995/04/13 19:53:48 simons Exp $
  24.  *
  25.  */
  26.  
  27. /************************************* includes ***********/
  28. #include <exec/types.h>
  29. #include <exec/memory.h>
  30. #include <sys/types.h>
  31. #include <sys/socket.h>
  32. #include <sys/param.h>
  33. #include <dos/dos.h>
  34. #include <dos/dosextens.h>
  35. #include <dos/dostags.h>
  36. #include <proto/dos.h>
  37. #include <proto/exec.h>
  38. #include <proto/utility.h>
  39. #include <proto/usergroup.h>
  40. #include <errno.h>
  41. #include <sys/ioctl.h>
  42. #include <exec/errors.h>
  43. #include <devices/serial.h>
  44. #include <string.h>
  45. #include <stdlib.h>
  46. #include <stdio.h>
  47. #include <inetd.h>
  48. #include <syslog.h>
  49. #include <amitcp/socketbasetags.h>
  50.  
  51. #include <fakesr.h>
  52.  
  53. #include "telnetd_rev.h"
  54.  
  55. /************************************* structures *********/
  56. struct InstData {
  57.         struct Library *DOSB;
  58.         struct Library *SocketB;
  59.         struct Library *UtilityB;
  60.         struct Library *UserGroupB;
  61.         int Socket;
  62.         signed short RecvBuf[1024];
  63.         int RecvBufPos;
  64.         int RecvBufFlags;
  65. };
  66.  
  67. struct PasswdInfo {
  68.         char Login[50];
  69.         char Passwd[50];
  70.         char RealName[150];
  71.         char WorkDir[256];
  72.         char Command[512];
  73. };
  74.  
  75. /************************************* defines ************/
  76. #define DOSBase Inst->DOSB
  77. #define UtilityBase Inst->UtilityB
  78. #define SocketBase Inst->SocketB
  79. #define UserGroupBase Inst->UserGroupB
  80. #define Socket Inst->Socket
  81.  
  82. /* telnet symbols */
  83. #define IAC 255
  84. #define WILL 251
  85. #define WONT 252
  86. #define DO 253
  87. #define DONT 254
  88. #define ECHO 1
  89. #define LINEMODE 34
  90. #define SE 240
  91. #define SB 250
  92. #define MODE 1
  93. #define EDIT 1
  94.  
  95. #define RBF_SUBNEGOTIATE (1<<0)         /* Defines for RecvBufFlags */
  96.  
  97. /************************************* global variables ***/
  98. static const char __DOSVer[] = VERSTAG " written by Peter Simons <simons@peti.rhein.de>";
  99. #ifndef USE_INETD
  100. struct Library *SysBase;
  101. #endif
  102. char *Signature="FAKEMSG--EXPUNGE";
  103.  
  104. /************************************* prototypes *********/
  105. void SockPuts(struct InstData *Inst,int Sock,char *Buf);
  106. void SockGets(struct InstData *Inst,int Sock,char *Buf,int BufSize);
  107. unsigned long GetInt(char *String,char **NewPtr);
  108. struct PasswdInfo *LookupPasswd(struct InstData *Inst,char *Login);
  109. int __asm SubSubProc(register __a0 char *ArgString,register __d0 long Length);
  110. struct DosPacket *PktFromMsg(struct Message *Msg);
  111. void MakeLongStr(char *StrBuf,unsigned long Num);
  112. void SockWrite(struct InstData *Inst,int Sock,char *Buf,int Len,int RawFlag);
  113. int RecvChar(struct InstData *Inst,int Sock,unsigned char *Loc,int RawMode);
  114. struct Process *MyCreateNewProcTags(struct InstData *,ULONG,...);
  115. void *MyAllocDosObjectTags(struct InstData *,ULONG,ULONG,...);
  116. void PktFPuts(struct InstData *Inst,BPTR File,char *String);
  117. void SockRawWrite(struct InstData *Inst,int Sock,char *Buf,int Len);
  118. void MySystemTags(struct Library *DSBse,char *Cmd,ULONG Tag0,...);
  119. void mystrcat(char *Dest,char *Cat);
  120. void MyFPrintf(struct InstData *Inst,BPTR File,char *Fmt,...);
  121.  
  122. ULONG FakeBeginIO(void *IORequest);
  123. ULONG FakeAbortIO(void *IORequest);
  124. ULONG FakeOpen(void *IORequest);
  125. ULONG FakeClose(void *IORequest);
  126. void mymovmem(char *From,char *To,int Len);
  127.  
  128. #define NewList(list) {(list)->lh_Head=(struct Node *)&(list)->lh_Tail;(list)->lh_Tail=NULL;(list)->lh_TailPred=(struct Node *)&(list)->lh_Head;}
  129.  
  130. #ifdef DEBUG
  131.   BPTR DebugFile;
  132. #endif
  133.  
  134. #ifdef USE_INETD
  135. int main(void)
  136. #else
  137. int __asm main(register __a0 char *ArgStr,register __d0 long Length)
  138. /* ArgString will look like: "[SocketID] [SigNum] [ParentTaskID]" */
  139. #endif
  140. {
  141.         int Cnt;
  142.         unsigned long SockID,SigID,TaskID;
  143.         char Buf[1000],LoginBuf[50], MyPrgName[64];
  144.         BPTR BannerFile=NULL;
  145.         struct InstData *Inst=NULL;
  146.         struct PasswdInfo *Info=NULL;
  147.         struct FileHandle *FH;
  148.         struct Message *Msg,*GotMsg;
  149.         unsigned char NoEcho[7];
  150.         unsigned char Echo[14];
  151.         char *ArgString;
  152.         int OpenCount=0;
  153.         int AmntRead;
  154.         int HangupFlag=FALSE;
  155.  
  156.         ULONG SigMask;
  157.         long yes=TRUE;
  158.         fd_set RdSet;
  159.         fd_set WrSet;
  160.         struct List ReadWaitList;
  161.         struct DosPacket *Pkt;
  162.         int Err;
  163.         unsigned char Chr,NumBuf[30];
  164.         int RawMode=FALSE;
  165.         int NextChar=-1;
  166.         struct MsgPort *TimePort;
  167.         struct timerequest *TimeReq;
  168.         struct DaemonMessage *InetdStartup;
  169.         struct Process *Self;
  170.  
  171.  
  172. #ifndef USE_INETD
  173.         SysBase=*((struct Library **)0x00000004);
  174.         ArgString=ArgStr;
  175. #endif
  176.         Echo[0]=NoEcho[0]=IAC;
  177.         Echo[1]=WONT;
  178.         Echo[2]=ECHO;
  179.         Echo[3]=IAC;
  180.         Echo[4]=DO;
  181.         Echo[5]=LINEMODE;
  182.         Echo[6]=IAC;
  183.         Echo[7]=SB;
  184.         Echo[8]=LINEMODE;
  185.         Echo[9]=MODE;
  186.         Echo[10]=EDIT;
  187.         Echo[11]=IAC;
  188.         Echo[12]=SE;
  189.         NoEcho[1]=WILL;
  190.         NoEcho[2]=ECHO;
  191.         NoEcho[3]=IAC;
  192.         NoEcho[4]=DONT;
  193.         NoEcho[5]=LINEMODE;
  194.         Echo[13]=NoEcho[6]='\0';
  195.  
  196. #ifndef USE_INETD
  197.         for (Cnt=0;Cnt < Length;Cnt++) {
  198.                 if (ArgStr[Cnt]!=' ' && (ArgStr[Cnt] < '0' || ArgStr[Cnt] > '9'))
  199.                         return ERROR_FILE_NOT_OBJECT;
  200.         }
  201. #endif
  202.         Inst=AllocMem(sizeof(struct InstData),MEMF_CLEAR);
  203.         if (!Inst) return 0;
  204.         DOSBase=OpenLibrary("dos.library",36);
  205.         UtilityBase=OpenLibrary("utility.library",36);
  206.         SocketBase=OpenLibrary("bsdsocket.library",2);
  207.         UserGroupBase=OldOpenLibrary(USERGROUPNAME);
  208.  
  209.         TimePort=CreateMsgPort();
  210.         NewList(&ReadWaitList);
  211.  
  212.         if (!DOSBase || !UtilityBase || !SocketBase || !UserGroupBase || !TimePort) return 0;
  213.  
  214.         SocketBaseTags(SBTM_SETVAL(SBTC_LOGTAGPTR), "telnetd",
  215.                  SBTM_SETVAL(SBTC_LOGSTAT), 0,
  216.                  SBTM_SETVAL(SBTC_LOGFACILITY), LOG_AUTH,
  217.                  TAG_END);
  218.  
  219. #ifdef DEBUG
  220.         DebugFile=Open("con:0/0/500/100/telnetd DEBUG/WAIT/CLOSE",MODE_OLDFILE);
  221.         FPuts(DebugFile,"telnetd starting\n");
  222. #  ifndef USE_INETD
  223.         FPuts(DebugFile,"ArgString=");
  224.         FPuts(DebugFile,ArgString);
  225.         FPuts(DebugFile,"\n");
  226. #  endif
  227.  
  228. #endif
  229.  
  230. #ifdef USE_INETD
  231.         Self=(struct Process *) FindTask(NULL);
  232.         InetdStartup=(struct DaemonMessage *)Self->pr_ExitData;
  233.         if (!InetdStartup) goto quit;
  234.         Socket=ObtainSocket(InetdStartup->dm_Id,InetdStartup->dm_Family,InetdStartup->dm_Type,0);
  235.         if (Socket < 0) goto quit;
  236. #else
  237.         /* Get arguments */
  238.         SockID=GetInt(ArgString,&ArgString);
  239.         ArgString++; /* Skip over space */
  240.         SigID=GetInt(ArgString,&ArgString);
  241.         ArgString++; /* Skip over space */
  242.         TaskID=GetInt(ArgString,&ArgString);
  243.         /* After this call, the parameter string is no longer valid */
  244.         Signal((struct Task *)TaskID,1<<SigID);
  245. #ifdef DEBUG
  246.         FPuts(DebugFile,"Signaled parent\n");
  247. #endif
  248.  
  249.         /* We're on our own now */
  250.         Socket=ObtainSocket(SockID,AF_INET,SOCK_STREAM,0);
  251.         if (Socket < 0) goto quit;
  252.  
  253. #endif
  254.  
  255. #ifdef DEBUG
  256.         FPuts(DebugFile,"Got Socket\n");
  257. #endif
  258.  
  259.         /* First, display banner, ask for password, etc */
  260.         if (BannerFile=Open("AmiTCP:db/telnetd_banner",MODE_OLDFILE)) {
  261.                 int len = 1;
  262.  
  263.                 while(TRUE) {
  264.                         len = Read(BannerFile, Buf, sizeof(Buf));
  265.                         if (!len || len == -1)
  266.                                 break;
  267.                         SockWrite(Inst,Socket,Buf,len,FALSE);
  268.                 }
  269.                 Close(BannerFile);
  270.         }
  271.  
  272. #ifdef DEBUG
  273.         FPuts(DebugFile,"Wrote banner to socket\n");
  274. #endif
  275.         /* Get login name */
  276.         SockPuts(Inst,Socket,"Login: ");
  277.         SockPuts(Inst,Socket,Echo);
  278.         SockGets(Inst,Socket,LoginBuf,sizeof(LoginBuf));
  279.         while (strlen(LoginBuf) && (LoginBuf[strlen(LoginBuf)-1]=='\n' || LoginBuf[strlen(LoginBuf)-1]=='\r'))
  280.                 LoginBuf[strlen(LoginBuf)-1]='\0';
  281. #ifdef DEBUG
  282.         FPuts(DebugFile,"Got Login: ");
  283.         FPuts(DebugFile,LoginBuf);
  284.         FPuts(DebugFile,"\n");
  285. #endif
  286.  
  287.         Info = LookupPasswd(Inst, LoginBuf);
  288.  
  289.  
  290.         /*
  291.          * We don't need a password if the password is "*"
  292.          * AND the shell is not equal "nologin".
  293.          *
  294.          * Otherwise get a password, even if the user doesn't exist at all.
  295.          */
  296.         if (!Info || !(!strcmp(Info->Passwd, "*") && strcmp("nologin", Info->Command))) {
  297.                 strcpy(Buf, "Password: ");
  298.                 strcpy(Buf+strlen(Buf), NoEcho);
  299.                 SockPuts(Inst, Socket, Buf);
  300.                 SockGets(Inst, Socket, Buf,sizeof(Buf));
  301.                 while (strlen(Buf) && (Buf[strlen(Buf)-1]=='\n' || Buf[strlen(Buf)-1]=='\r'))
  302.                         Buf[strlen(Buf)-1]='\0';
  303.                 SockPuts(Inst,Socket,Echo);
  304. #ifdef DEBUG
  305.                 FPuts(DebugFile,"Got Password: ");
  306.                 FPuts(DebugFile,Buf);
  307.                 FPuts(DebugFile,"\n");
  308. #endif
  309.                 if (!Info || !strcmp("nologin", Info->Command) || strcmp(Info->Passwd, crypt(Buf, Info->Passwd))) {
  310.             if (Info)
  311.               syslog(LOG_INFO, "Unsuccessful login attempt from user %s", Info->Login);
  312.                         SockPuts(Inst,Socket,"\nLogin incorrect.\nClosing connection\n");
  313.                         CloseSocket(Socket);
  314.                         goto quit;
  315.                 }
  316.         }
  317.  
  318.         SockPuts(Inst,Socket,"\n");
  319.  
  320.     syslog(LOG_INFO, "User %s logged in successfully", Info->Login);
  321.     sprintf(MyPrgName, "telnetd <%s>", Info->Login);
  322.     SetProgramName(MyPrgName);
  323.  
  324.         if (Info->Command[0]=='*') {
  325.                 /* Use stdin/stdout */
  326.                 /* Make myself a filehandle */
  327. #ifdef DEBUG
  328.                 FPuts(DebugFile,"Logged in OK\nMaking Filehandle\n");
  329. #endif
  330.  
  331.                 FH=MyAllocDosObjectTags(Inst,DOS_FILEHANDLE,ADO_FH_Mode,MODE_OLDFILE,TAG_END);
  332.                 if (!FH) goto quit;
  333.                 FH->fh_Pos=FH->fh_End=-1;
  334.                 FH->fh_Type=&((struct Process *)FindTask(NULL))->pr_MsgPort;
  335.                 FH->fh_Args=(LONG)Info;
  336.                 FH->fh_Port=FH->fh_Type; /* Is this right? */
  337.                 FH=(struct FileHandle *)MKBADDR(FH);
  338.                 OpenCount++;
  339.  
  340.                 /* Run the subprocess */
  341.                 MakeLongStr(Buf,(ULONG)FH);
  342.                 strcpy(Buf+strlen(Buf)," ");
  343.                 strcpy(Buf+strlen(Buf),Info->Command+1 /* ignore the leading '*' */);
  344. #ifdef DEBUG
  345.                 FPuts(DebugFile,"Starting subprocess\nCmdLine=");
  346.                 FPuts(DebugFile,Buf);
  347.                 FPuts(DebugFile,"\n");
  348.                 /*Close(DebugFile);*/
  349.                 Flush(DebugFile);
  350.  
  351.                 /*DebugFile=NULL;*/
  352. #endif
  353.  
  354.                 /* NO more DOS calls allowed after this one */
  355.                 /* We also can't use Buf after we make this call */
  356.     if (*(Info->Command+1)) {
  357.                 MyCreateNewProcTags(Inst,NP_Entry,SubSubProc,
  358.                     NP_Arguments,Buf,
  359.                     TAG_END);
  360.     }
  361.                 FD_ZERO(&RdSet);
  362.                 IoctlSocket(Socket,FIONBIO,(caddr_t)&yes);
  363. #ifdef DEBUG
  364.                 PktFPuts(Inst,DebugFile,"Starting handler support\n");
  365. #endif
  366.                 for (;;) {
  367.                         if (ReadWaitList.lh_Head->ln_Succ && !HangupFlag) {
  368.                                 if (NextChar != -1) {
  369.                                         Pkt=PktFromMsg((struct Message *)ReadWaitList.lh_Head);
  370.                                         *(((unsigned char *)Pkt->dp_Arg2)+Pkt->dp_Res1)=NextChar;
  371.                                         Chr=NextChar;
  372.                                         NextChar=-1;
  373.                                         Err=1;
  374.                                         Pkt->dp_Res1++;
  375.                                         if (Pkt->dp_Res1==Pkt->dp_Arg3 || Chr=='\r' || Chr=='\n') {
  376.                                                 Remove(ReadWaitList.lh_Head);
  377.                                                 PutMsg(Pkt->dp_Port,Pkt->dp_Link); /* Send it back */
  378.                                         }
  379.                                 }
  380.                         }
  381.                         if (ReadWaitList.lh_Head->ln_Succ && !HangupFlag) {
  382.                                 FD_SET(Socket,&RdSet);
  383.                         } else {
  384.                                 FD_CLR(Socket,&RdSet);
  385.                         }
  386.                         SigMask=(1<<((struct Process *)FindTask(NULL))->pr_MsgPort.mp_SigBit)|(1<<TimePort->mp_SigBit);
  387.                         WaitSelect(Socket+1,&RdSet,NULL,NULL,NULL,&SigMask);
  388. #ifdef DEBUG
  389.                         PktFPuts(Inst,DebugFile,"Wait ended \n");
  390. #endif
  391.  
  392.                         if (FD_ISSET(Socket,&RdSet)) {
  393. #ifdef DEBUG
  394.                                 PktFPuts(Inst,DebugFile,"Got read available from socket\n");
  395. #endif
  396.                                 if (ReadWaitList.lh_Head->ln_Succ) {
  397.                                         /* Someone is waiting to read */
  398.                                         Pkt=PktFromMsg((struct Message *)ReadWaitList.lh_Head);
  399.                                         if (Pkt && Pkt->dp_Type==ACTION_READ) {
  400. #ifdef DEBUG
  401.                                                 PktFPuts(Inst,DebugFile,"Performing delayed read\n");
  402. #endif
  403.                                                 while (Pkt->dp_Res1 < Pkt->dp_Arg3) {
  404.                                                         if (NextChar != -1) {
  405.                                                                 *(((unsigned char *)Pkt->dp_Arg2)+Pkt->dp_Res1)=NextChar;
  406.                                                                 Chr=NextChar;
  407.                                                                 NextChar=-1;
  408.                                                                 Err=1;
  409.                                                         } else {
  410.                                                                 Err=RecvChar(Inst,Socket,((char *)Pkt->dp_Arg2)+Pkt->dp_Res1,FALSE/*RawMode*/);
  411.                                                                 Chr=*(((char *)Pkt->dp_Arg2)+Pkt->dp_Res1);
  412.                                                         }
  413.                                                         if (Err==1) Pkt->dp_Res1++;
  414.                                                         else if (Err==0) {
  415.                                                                 /* Hangup */
  416.                                                                 HangupFlag=TRUE;
  417.                                                                 break;
  418.                                                         } else break;
  419. #ifdef DEBUG
  420.                                                         if (Chr==255) {
  421.                                                                 PktFPuts(Inst,DebugFile,"Received 255\n");
  422.                                                         }
  423. #endif
  424.                                                         if (Chr=='\r' || Chr=='\n') {
  425.                                                                 break;
  426.                                                         }
  427.                                                 }
  428.                                                 if (Err==1) {
  429.                                                         if (Pkt->dp_Res1==Pkt->dp_Arg3 ||
  430.                                 Chr=='\r' || Chr=='\n') {
  431.                                                                 Remove(ReadWaitList.lh_Head);
  432. /*                                 syslog(LOG_DEBUG, "Sending out \"%s\"",
  433.  *                                        &Pkt->dp_Link+sizeof(struct Message));
  434.  */
  435.                                                                 PutMsg(Pkt->dp_Port,Pkt->dp_Link); /* Send it back */
  436.                                                         }
  437.                                                 }
  438.                                         } else if (Pkt && Pkt->dp_Type==ACTION_WAIT_CHAR) {
  439. #ifdef DEBUG
  440.                                                 PktFPuts(Inst,DebugFile,"Processing WAIT_CHAR");
  441. #endif
  442.                                                 if (NextChar==-1) {
  443.                                                         Err=RecvChar(Inst,Socket,&Chr,FALSE);
  444.                                                         if (Err==1) {
  445.                                                                 Pkt->dp_Res1=DOSTRUE;
  446.                                                                 Remove(ReadWaitList.lh_Head);
  447. #ifdef DEBUG
  448.                                                                 PktFPuts(Inst,DebugFile,"char ready\n");
  449. #endif
  450.                                                                 AbortIO((struct IORequest *)Pkt->dp_Res2);
  451.                                                                 WaitIO((struct IORequest *)Pkt->dp_Res2);
  452.                                                                 CloseDevice((struct IORequest *)Pkt->dp_Res2);
  453.                                                                 DeleteIORequest((struct IORequest *)Pkt->dp_Res2);
  454.                                                                 Pkt->dp_Res2=0;
  455.                                                                 PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  456.                                                                 NextChar=Chr;
  457.                                                         } else {
  458. #ifdef DEBUG
  459.                                                                 PktFPuts(Inst,DebugFile,"no char available\n");
  460. #endif
  461.                                                                 NextChar=-1;
  462.                                                         }
  463.                                                         if (Err==0) HangupFlag=TRUE;
  464.                                                 } else {
  465.                                                         Pkt->dp_Res1=DOSTRUE;
  466.                                                         Remove(ReadWaitList.lh_Head);
  467.                                                         AbortIO((struct IORequest *)Pkt->dp_Res2);
  468.                                                         WaitIO((struct IORequest *)Pkt->dp_Res2);
  469.                                                         CloseDevice((struct IORequest *)Pkt->dp_Res2);
  470.                                                         DeleteIORequest((struct IORequest *)Pkt->dp_Res2);
  471.                                                         Pkt->dp_Res2=0;
  472.                                                         PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  473. #ifdef DEBUG
  474.                                                         PktFPuts(Inst,DebugFile,"char ready\n");
  475. #endif
  476.                                                 }
  477.                                         }
  478.                                         else { /* Invalid message */
  479.                                                 Remove(ReadWaitList.lh_Head);
  480.                                         }
  481.                                 } else {
  482. #ifdef DEBUG
  483.                                         PktFPuts(Inst,DebugFile,"Unexpected: got read ready, no request\n");
  484. #endif
  485.                                 }
  486.                         }
  487.                         while (TimeReq=(struct timerequest *)GetMsg(TimePort)) {
  488.                                 Msg=(struct Message *)TimeReq->tr_node.io_Message.mn_Node.ln_Name;
  489.                                 Pkt=PktFromMsg(Msg);
  490.                                 CloseDevice(TimeReq);
  491.                                 DeleteIORequest(TimeReq);
  492.                                 Pkt->dp_Res1=DOSFALSE;
  493.                                 Pkt->dp_Res2=0;
  494.                                 Remove(Msg); /* Remove it from the read wait list */
  495.                                 PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  496.  
  497.  
  498.                         }
  499.                         while (Msg=GetMsg(&((struct Process *)FindTask(NULL))->pr_MsgPort)) {
  500.                                 Pkt=PktFromMsg(Msg);
  501. #ifdef DEBUG
  502.                                 PktFPuts(Inst,DebugFile,"Got packet\n");
  503. #endif
  504.                                 switch(Pkt->dp_Type) {
  505.                                         case ACTION_FINDINPUT:
  506.                                         case ACTION_FINDOUTPUT:
  507.                                         case ACTION_FINDUPDATE:
  508.                                                 FH=(struct FileHandle *)BADDR((BPTR)Pkt->dp_Arg1);
  509.                                                 FH->fh_Pos=FH->fh_End=-1;
  510.                                                 FH->fh_Type=&((struct Process *)FindTask(NULL))->pr_MsgPort;
  511.                                                 FH->fh_Args=(LONG)Info;
  512.                                                 FH->fh_Port=FH->fh_Type; /* Is this right? */
  513.                                                 OpenCount++;
  514.                                                 Pkt->dp_Res1=DOSTRUE;
  515.                                                 PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  516.                                         break;
  517.  
  518.                                         case ACTION_READ:
  519.                                         Pkt->dp_Res1=0;
  520. #ifdef DEBUG
  521.                                         PktFPuts(Inst,DebugFile,"Got action_read\n");
  522. #endif
  523.                                         AddTail(&ReadWaitList,Msg);
  524.                                         break;
  525.  
  526.                                         case ACTION_WRITE:
  527. #ifdef DEBUG
  528.                                         PktFPuts(Inst,DebugFile,"Got action_write\n");
  529. #endif
  530.                                         SockWrite(Inst,Socket,(char *)Pkt->dp_Arg2,Pkt->dp_Arg3,FALSE/*RawMode*/);
  531.                                         Pkt->dp_Res1=Pkt->dp_Arg3;
  532.                                         PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  533.                                         break;
  534.  
  535.                                         case ACTION_WAIT_CHAR:
  536. #ifdef DEBUG
  537.                                                 PktFPuts(Inst,DebugFile,"Got action_waitchar");
  538. #endif
  539.                                                 Pkt->dp_Res1=DOSFALSE;
  540.  
  541.                                                 TimeReq=CreateIORequest(TimePort,sizeof(struct timerequest));
  542.                                                 if (!TimeReq || OpenDevice("timer.device",UNIT_MICROHZ,TimeReq,0)) {
  543.                                                         if (TimeReq)
  544.                               DeleteIORequest(TimeReq);
  545.                                                         Pkt->dp_Res2=ERROR_NO_FREE_STORE;
  546.                                                         PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  547.                                                 }
  548.                                                 TimeReq->tr_node.io_Command=TR_ADDREQUEST;
  549.                                                 TimeReq->tr_time.tv_micro=Pkt->dp_Arg1;
  550.                                                 TimeReq->tr_time.tv_secs=0;
  551.                                                 TimeReq->tr_node.io_Message.mn_Node.ln_Name=Msg;
  552.                                                 SendIO(TimeReq);
  553.                                                 Pkt->dp_Res2=(ULONG)TimeReq;
  554.  
  555.                                                 AddTail(&ReadWaitList,Msg);
  556.  
  557.                                         break;
  558.  
  559.         /*
  560.                                         case ACTION_DISKINFO:
  561.  
  562.                                         break;
  563.                                         */
  564.                                         case ACTION_SCREEN_MODE:
  565. #ifdef DEBUG
  566.                                         PktFPuts(Inst,DebugFile,"Got action_screen_mode\n");
  567. #endif
  568.                                                 if (Pkt->dp_Arg1) {
  569.                                                         /* Raw mode */
  570.                                                         SockPuts(Inst,Socket,NoEcho);
  571.                                                         RawMode=TRUE;
  572.                                                 } else {
  573.                                                         SockPuts(Inst,Socket,Echo);
  574.                                                         RawMode=FALSE;
  575.                                                 }
  576.                                                 Pkt->dp_Res1=DOSFALSE;
  577.                                                 PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  578.                                         break;
  579.  
  580.                                         case ACTION_END:
  581. #ifdef DEBUG
  582.                                         PktFPuts(Inst,DebugFile,"Got action_end\n");
  583. #endif
  584.                                                 Pkt->dp_Res1=0;
  585.                                                 PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  586.                                                 OpenCount--;
  587.                                                 if (!OpenCount) {
  588.                                                         for (GotMsg=(struct Message *)ReadWaitList.lh_Head;GotMsg->mn_Node.ln_Succ;GotMsg=(struct Message *)GotMsg->mn_Node.ln_Succ) {
  589.                                                                 Pkt=PktFromMsg(GotMsg);
  590.                                                                 if (Pkt->dp_Type==ACTION_WAIT_CHAR) {
  591.                                                                         AbortIO((struct IORequest *)Pkt->dp_Res2);
  592.                                                                         WaitIO((struct IORequest *)Pkt->dp_Res2);
  593.                                                                         CloseDevice((struct IORequest *)Pkt->dp_Res2);
  594.                                                                         DeleteIORequest((struct IORequest *)Pkt->dp_Res2);
  595.                                                                         Pkt->dp_Res2=0;
  596.                                                                 }
  597.                                                         }
  598.  
  599.                                                         goto quit;
  600.                                                 }
  601.                                         break;
  602.  
  603.                                         case ACTION_SEEK:
  604. #ifdef DEBUG
  605.                                         PktFPuts(Inst,DebugFile,"Got action_seek\n");
  606. #endif
  607.                                         Pkt->dp_Res1=-1;
  608.                                         Pkt->dp_Res2=ERROR_OBJECT_WRONG_TYPE;
  609.                                         PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  610.  
  611.                                         break;
  612.  
  613.  
  614.                                         default:
  615. #ifdef DEBUG
  616.                                         PktFPuts(Inst,DebugFile,"Got action_not_known. Number");
  617.                                         MakeLongStr(NumBuf,Pkt->dp_Type);
  618.                                         PktFPuts(Inst,DebugFile,NumBuf);
  619.                                         PktFPuts(Inst,DebugFile,"\n");
  620. #endif
  621.                                         Pkt->dp_Res1=0;
  622.                                         Pkt->dp_Res2=ERROR_ACTION_NOT_KNOWN;
  623.                                         PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  624.                                 }
  625.                         }
  626.                 }
  627.         } else {
  628.                 /* Use fake serial */
  629.                 struct IOStdReq *IOReq=NULL;
  630.                 struct MsgPort *IOPort=NULL;
  631.                 struct FSRUnit *SerUnit=NULL;
  632.                 /* SerUnit->fsru_UserData[0]=CmdPort
  633.                    SerUnit->fsru_UserData[1]=ReadQueue
  634.                          SerUnit->fsru_UserData[2]=WriteQueue
  635.                          SerUnit->fsru_UserData[3]=Open count
  636.                          SerUnit->fsru_UserData[4]=RBufLen */
  637.                 struct MsgPort *CmdPort=NULL;
  638.                 struct List *ReadQueue=NULL;
  639.                 struct List *WriteQueue=NULL;
  640.                 char *CmdPtr;
  641.                 struct IOExtSer *GotReq=NULL,*OtrReq=NULL;
  642.                 char *RBuf=NULL;
  643.                 int RBufPos=0;
  644.                 int SerUnitAdded=FALSE;
  645.                 int Amnt;
  646.                 int RecvRet;
  647.                 int CD=TRUE; /* Carrier Detect */
  648.                 long UnitNum=FSR_UNITNONE;
  649.  
  650.                 /* We use IOExtSer.Status bit 0 as a flag to say whether this request has
  651.                    been aborted */
  652.  
  653. #ifdef DEBUG
  654.                 FPuts(DebugFile,"Creating ports...\n");
  655. #endif
  656.                 IOPort=CreateMsgPort();
  657.                 CmdPort=CreateMsgPort();
  658.                 IOReq=CreateIORequest(IOPort,sizeof(struct IOStdReq));
  659.                 if (!IOPort || !IOReq || !CmdPort) {
  660. #ifdef DEBUG
  661.                         FPuts(DebugFile,"Unable to create message port/IORequest\nExiting\n");
  662. #endif
  663.                         goto quitfakeser;
  664.                 }
  665. #ifdef DEBUG
  666.                 FPuts(DebugFile,"Opening fakesr.device...\n");
  667. #endif
  668.                 if (OpenDevice("fakesr.device",FSR_CTLUNIT,IOReq,0)) {
  669.                         IOReq->io_Device=NULL;
  670. #ifdef DEBUG
  671.                         FPuts(DebugFile,"Unable to open fakesr.device\nExiting\n");
  672. #endif
  673.                         goto quitfakeser;
  674.                 }
  675. #ifdef DEBUG
  676.                 FPuts(DebugFile,"opened successfully\n");
  677. #endif
  678.                 SerUnit=AllocMem(sizeof(struct FSRUnit),MEMF_CLEAR|MEMF_PUBLIC);
  679.                 ReadQueue=AllocMem(sizeof(struct List),MEMF_PUBLIC);
  680.                 if (ReadQueue) NewList(ReadQueue);
  681.                 WriteQueue=AllocMem(sizeof(struct List),MEMF_PUBLIC);
  682.                 if (WriteQueue) NewList(WriteQueue);
  683.                 if (!SerUnit || !ReadQueue || !WriteQueue) {
  684. #ifdef DEBUG
  685.                         FPuts(DebugFile,"Unable to allocate memory\nExiting\n");
  686. #endif
  687.                         goto quitfakeser;
  688.                 }
  689.  
  690.                 CmdPtr=Info->Command;
  691.                 if (Info->Command[0]<='9' && Info->Command[0] >= '0') {
  692.                         UnitNum=GetInt(Info->Command,&CmdPtr);
  693.                 }
  694.  
  695.                 SerUnit->fsru_Num=UnitNum;
  696.                 SerUnit->fsru_BeginIO=FakeBeginIO;
  697.                 SerUnit->fsru_AbortIO=FakeAbortIO;
  698.                 SerUnit->fsru_Open=FakeOpen;
  699.                 SerUnit->fsru_Close=FakeClose;
  700.                 SerUnit->fsru_UserData[0]=CmdPort;
  701.                 SerUnit->fsru_UserData[1]=ReadQueue;
  702.                 SerUnit->fsru_UserData[2]=WriteQueue;
  703.                 SerUnit->fsru_UserData[3]=0;
  704.                 SerUnit->fsru_UserData[4]=(void *)1024;
  705.  
  706.                 IOReq->io_Data=(APTR)SerUnit;
  707.                 IOReq->io_Length=sizeof(*SerUnit);
  708.                 IOReq->io_Command=FSRCMD_ADDUNIT;
  709.                 IOReq->io_Error=0;
  710. #ifdef DEBUG
  711.                 FPuts(DebugFile,"Adding FakeSr unit...");
  712. #endif
  713.  
  714.                 DoIO(IOReq);
  715.                 if (IOReq->io_Error) {
  716. #ifdef DEBUG
  717.                         FPuts(DebugFile,"Error adding fakesr.device unit\nExiting\n");
  718. #endif
  719.                         goto quitfakeser;
  720.                 }
  721.  
  722.                 SerUnitAdded=TRUE;
  723.  
  724. #ifdef DEBUG
  725.                 FPuts(DebugFile,"Done\n");
  726. #endif
  727.  
  728.                 RBuf=AllocMem((ULONG)SerUnit->fsru_UserData[4],MEMF_PUBLIC);
  729.                 RBufPos=0;
  730.                 if (!RBuf) {
  731. #ifdef DEBUG
  732.                         FPuts(DebugFile,"Unable to allocate memory\nExiting\n");
  733. #endif
  734.                         goto quitfakeser;
  735.                 }
  736.  
  737.  
  738.                 IoctlSocket(Socket,FIONBIO,(caddr_t)&yes);
  739.                 {
  740.                         BPTR NilInput,NilOutput;
  741. #ifdef DEBUG
  742.                         FPuts(DebugFile,"Opening filehandles\n");
  743. #endif
  744.       if (*CmdPtr) {
  745.                           NilInput=Open("NIL:",MODE_OLDFILE);
  746.                           NilOutput=Open("NIL:",MODE_OLDFILE);
  747.  
  748.                           /* sprintf(Buf,"%s -DEVICE fakesr.device -UNIT %ld",CmdPtr,SerUnit->fsru_Num); */
  749.                           strcpy(Buf,CmdPtr);
  750.                           mystrcat(Buf," -DEVICE fakesr.device -UNIT ");
  751.                           MakeLongStr(LoginBuf,SerUnit->fsru_Num);
  752. #ifdef DEBUG
  753.                           FPuts(DebugFile,"Got FakeSr unit: ");
  754.                           FPuts(DebugFile,LoginBuf);
  755.                           FPuts(DebugFile,"\n");
  756. #endif
  757.                           SockPuts(Inst,Socket,NoEcho);
  758.  
  759.                           mystrcat(Buf,LoginBuf);
  760. #ifdef DEBUG
  761.                           FPuts(DebugFile,"Running command:");
  762.                           FPuts(DebugFile,Buf);
  763.                           FPuts(DebugFile,"\n");
  764. #endif
  765.                           MySystemTags(DOSBase,Buf,SYS_Input,NilInput,SYS_Output,NilOutput,SYS_Asynch,TRUE,TAG_END);
  766.       }
  767.                 }
  768.  
  769.                 for (;;) {
  770.                         FD_ZERO(&RdSet);
  771.                         FD_ZERO(&WrSet);
  772.                         if (CD)  {
  773.                                 if (RBufPos < (((long)SerUnit->fsru_UserData[4])-1)) FD_SET(Socket,&RdSet);
  774.                                 if (WriteQueue->lh_Head->ln_Succ) FD_SET(Socket,&WrSet);
  775.                         }
  776.                         SigMask=(1<<CmdPort->mp_SigBit)|SIGBREAKF_CTRL_C;
  777.                         WaitSelect(Socket+1,&RdSet,&WrSet,NULL,NULL,&SigMask);
  778. #ifdef DEBUG
  779.                         FPuts(DebugFile,"Wait ended...");
  780. #endif
  781.  
  782.                         if (FD_ISSET(Socket,&RdSet)) {
  783.                                 while ((RBufPos < (long)SerUnit->fsru_UserData[4]) && ((RecvRet=RecvChar(Inst,Socket,RBuf+RBufPos,TRUE))==1)) RBufPos++;
  784.                                 Forbid();
  785.                                 if ((GotReq=(struct IOExtSer *)ReadQueue->lh_Head)->IOSer.io_Message.mn_Node.ln_Succ) {
  786.                                         Remove(GotReq);
  787.                                         Permit();
  788.                                         Amnt=min(RBufPos,GotReq->IOSer.io_Length);
  789.                                         memcpy(((char *)GotReq->IOSer.io_Data)+GotReq->IOSer.io_Actual,RBuf,Amnt);
  790.                                         GotReq->IOSer.io_Actual+=Amnt;
  791.                                         if (Amnt < RBufPos) mymovmem(RBuf+Amnt,RBuf,RBufPos-Amnt);
  792.                                         RBufPos-=Amnt;
  793.  
  794.                                         if (GotReq->IOSer.io_Actual < GotReq->IOSer.io_Length) {
  795.                                                 if (GotReq->io_Status & (1<<0)) {
  796.                                                         /* We got an AbortIO() */
  797.                                                         GotReq->IOSer.io_Error=IOERR_ABORTED;
  798.                                                         ReplyMsg(GotReq);
  799.                                                 } else {
  800.                                                         Forbid();
  801.                                                         AddTail(ReadQueue,GotReq);
  802.                                                         Permit();
  803.                                                 }
  804.                                         }
  805.                                         else ReplyMsg(GotReq);
  806.  
  807.                                 }
  808.                                 else Permit();
  809.                                 if (RecvRet==0) {
  810.                                         /* Connection closed */
  811.                                         CD=FALSE;
  812.                                 }
  813.                         }
  814.                         if (FD_ISSET(Socket,&WrSet)) {
  815.                                 Forbid();
  816.                                 if ((GotReq=(struct IOExtSer *)WriteQueue->lh_Head)->IOSer.io_Message.mn_Node.ln_Succ) {
  817.                                         Remove(GotReq);
  818.                                         Permit();
  819.  
  820. #ifdef DEBUG
  821.                                         FPuts(DebugFile,"Writing to socket\n");
  822.                                         MyFPrintf(Inst,DebugFile,"io_Actual=%ld,io_Length=%ld\n",(long)GotReq->IOSer.io_Actual,(long)GotReq->IOSer.io_Length);
  823. #endif
  824.                                         SockWrite(Inst,Socket,((char *)GotReq->IOSer.io_Data)+GotReq->IOSer.io_Actual,GotReq->IOSer.io_Length-GotReq->IOSer.io_Actual,TRUE);
  825. #ifdef DEBUG
  826.                                         FPuts(DebugFile,"Write completed\n");
  827. #endif
  828.                                         GotReq->IOSer.io_Actual=GotReq->IOSer.io_Length;
  829.  
  830.  
  831.                                         if (GotReq->IOSer.io_Actual < GotReq->IOSer.io_Length) {
  832.                                                 Forbid();
  833.                                                 if (GotReq->io_Status & (1<<0)) {
  834.                                                         Permit();
  835.                                                         /* We got an AbortIO() */
  836.                                                         GotReq->IOSer.io_Error=IOERR_ABORTED;
  837.                                                         ReplyMsg(GotReq);
  838.                                                 } else {
  839.                                                         AddTail(WriteQueue,GotReq);
  840.                                                         Permit();
  841.                                                 }
  842.                                         } else {
  843. #ifdef DEBUG
  844.                                                 FPuts(DebugFile,"Replying write message\n");
  845. #endif
  846.                                                 ReplyMsg(GotReq);
  847.                                         }
  848.  
  849.  
  850.                                 } else {
  851.  
  852.                                         Permit();
  853.                                 }
  854.                         }
  855.                         while (GotReq=(struct IOExtSer *)GetMsg(CmdPort)) {
  856.                                 if (GotReq->IOSer.io_Message.mn_Node.ln_Name==Signature) {
  857.                                         /* We just use the pointer as a signature */
  858.                                         /* We just got an expunge request */
  859. #ifdef DEBUG
  860.                                         FPuts(DebugFile,"Got expunge request\n");
  861. #endif
  862.  
  863.                                         FreeMem(GotReq,sizeof(struct Message)); /* We free the expunge request instead of reply */
  864.  
  865.                                         Forbid();
  866.                                         if (SerUnit->fsru_UserData[3]==0) {
  867.                                                 /* Open count==0 */
  868.                                                 if (SerUnitAdded) {
  869.                                                         IOReq->io_Command=FSRCMD_REMUNIT;
  870.                                                         IOReq->io_Data=(APTR)SerUnit;
  871.                                                         IOReq->io_Length=sizeof(*SerUnit);
  872.                                                         DoIO(IOReq);
  873.                                                         SerUnitAdded=FALSE;
  874.                                                 }
  875.                                                 if (SerUnit->fsru_UserData[3]==0) {
  876.                                                         /* If opencnt is still 0 */
  877.                                                         Permit();
  878.                                                         goto quitfakeser; /* exit */
  879.                                                 }
  880.                                         }
  881.                                         Permit();
  882.                                 }
  883.                                 else {
  884. #ifdef DEBUG
  885.                                         FPuts(DebugFile,"Got cmd...");
  886. #endif
  887.  
  888.                                         switch(GotReq->IOSer.io_Command) {
  889.                                                 case CMD_CLEAR:
  890. #ifdef DEBUG
  891.                                                         FPuts(DebugFile,"Got CMD_CLEAR\n");
  892. #endif
  893.                                                         RBufPos=0;
  894.                                                         GotReq->IOSer.io_Error=0;
  895.                                                         ReplyMsg(GotReq);
  896.                                                 break;
  897.  
  898.                                                 case CMD_FLUSH:
  899.                                                 case CMD_RESET:
  900. #ifdef DEBUG
  901.                                                         FPuts(DebugFile,"Got CMD_FLUSH/RESET\n");
  902. #endif
  903.  
  904.                                                         Forbid();
  905.                                                         while (OtrReq=(struct IOExtSer *)RemHead(ReadQueue)) {
  906.                                                                 OtrReq->IOSer.io_Error=IOERR_ABORTED;
  907.                                                                 ReplyMsg(OtrReq);
  908.                                                         }
  909.                                                         while (OtrReq=(struct IOExtSer *)RemHead(WriteQueue)) {
  910.                                                                 OtrReq->IOSer.io_Error=IOERR_ABORTED;
  911.                                                                 ReplyMsg(OtrReq);
  912.                                                         }
  913.                                                         Permit();
  914.                                                         GotReq->IOSer.io_Error=0;
  915.                                                         ReplyMsg(GotReq);
  916.                                                 break;
  917.  
  918.                                                 case CMD_READ:
  919. #ifdef DEBUG
  920.                                                         FPuts(DebugFile,"Got CMD_READ\n");
  921. #endif
  922.  
  923.                                                         GotReq->IOSer.io_Actual=0;
  924.                                                         GotReq->IOSer.io_Error=0;
  925.                                                         Amnt=min(RBufPos,GotReq->IOSer.io_Length);
  926.                                                         memcpy(((char *)GotReq->IOSer.io_Data)+GotReq->IOSer.io_Actual,RBuf,Amnt);
  927.                                                         GotReq->IOSer.io_Actual+=Amnt;
  928.                                                         if (Amnt < RBufPos) mymovmem(RBuf+Amnt,RBuf,Amnt);
  929.                                                         RBufPos-=Amnt;
  930.  
  931.                                                         if (GotReq->IOSer.io_Actual < GotReq->IOSer.io_Length) {
  932.                                                                 Forbid();
  933.                                                                 AddTail(ReadQueue,GotReq);
  934.                                                                 Permit();
  935.                                                         }
  936.                                                         else ReplyMsg(GotReq);
  937.                                                 break;
  938.  
  939.                                                 case CMD_START:
  940. #ifdef DEBUG
  941.                                                         FPuts(DebugFile,"Got CMD_START\n");
  942. #endif
  943.  
  944.                                                         GotReq->IOSer.io_Error=0;
  945.                                                         ReplyMsg(GotReq);
  946.                                                 break;
  947.  
  948.                                                 case CMD_STOP:
  949. #ifdef DEBUG
  950.                                                         FPuts(DebugFile,"Got CMD_STOP\n");
  951. #endif
  952.  
  953.                                                         GotReq->IOSer.io_Error=0;
  954.                                                         ReplyMsg(GotReq);
  955.                                                 break;
  956.  
  957.                                                 case CMD_WRITE:
  958. #ifdef DEBUG
  959.                                                         FPuts(DebugFile,"Got CMD_WRITE\n");
  960. #endif
  961.  
  962.                                                         GotReq->IOSer.io_Actual=0;
  963.                                                         GotReq->IOSer.io_Error=0;
  964.                                                         Forbid();
  965.                                                         AddTail(WriteQueue,GotReq);
  966.                                                         Permit();
  967.                                                 break;
  968.  
  969.                                                 case SDCMD_BREAK:
  970. #ifdef DEBUG
  971.                                                         FPuts(DebugFile,"Got SDCMD_BREAK\n");
  972. #endif
  973.  
  974.                                                         GotReq->IOSer.io_Error=0;
  975.                                                         ReplyMsg(GotReq);
  976.                                                 break;
  977.  
  978.                                                 case SDCMD_QUERY:
  979. #ifdef DEBUG
  980.                                                         FPuts(DebugFile,"Got SDCMD_QUERY\n");
  981. #endif
  982.  
  983.                                                         GotReq->IOSer.io_Actual=RBufPos;
  984.                                                         GotReq->io_Status=0x0000 | ((CD) ? 0:(1<<5));
  985.                                                         GotReq->IOSer.io_Error=0;
  986.  
  987.                                                         ReplyMsg(GotReq);
  988.                                                 break;
  989.  
  990.                                                 case SDCMD_SETPARAMS:
  991. #ifdef DEBUG
  992.                                                         FPuts(DebugFile,"Got SDCMD_SETPARAMS\n");
  993. #endif
  994.  
  995.                                                         GotReq->IOSer.io_Error=0;
  996.                                                         ReplyMsg(GotReq);
  997.                                                 break;
  998.  
  999.                                                 default:
  1000. #ifdef DEBUG
  1001.                                                         FPuts(DebugFile,"Got CMD_UNKNOWN\n");
  1002. #endif
  1003.                                                         GotReq->IOSer.io_Error=IOERR_NOCMD;
  1004.                                                         ReplyMsg(GotReq);
  1005.  
  1006.                                         }
  1007.                                 }
  1008.                         }
  1009.                 }
  1010.  
  1011.  
  1012.                 quitfakeser:
  1013.  
  1014.                 if (ReadQueue) {
  1015.                         Forbid();
  1016.                         while (GotReq=(struct IOExtSer *)RemHead(ReadQueue)) {
  1017.                                 GotReq->IOSer.io_Error=IOERR_ABORTED;
  1018.                                 GotReq->IOSer.io_Actual=0;
  1019.                                 ReplyMsg(GotReq);
  1020.                         }
  1021.                         Permit();
  1022.                         FreeMem(ReadQueue,sizeof(struct List));
  1023.                 }
  1024.                 if (WriteQueue) {
  1025.                         Forbid();
  1026.                         while (GotReq=(struct IOExtSer *)RemHead(WriteQueue)) {
  1027.                                 GotReq->IOSer.io_Error=IOERR_ABORTED;
  1028.                                 GotReq->IOSer.io_Actual=0;
  1029.                                 ReplyMsg(GotReq);
  1030.                         }
  1031.                         Permit();
  1032.                         FreeMem(WriteQueue,sizeof(struct List));
  1033.                 }
  1034.                 if (RBuf && SerUnit) {
  1035.                         FreeMem(RBuf,(long)SerUnit->fsru_UserData[4]);
  1036.                 }
  1037.                 if (SerUnit) {
  1038.                         if (SerUnitAdded && IOReq) {
  1039.                                 IOReq->io_Data=(APTR)SerUnit;
  1040.                                 IOReq->io_Length=sizeof(*SerUnit);
  1041.                                 IOReq->io_Command=FSRCMD_REMUNIT;
  1042.                                 DoIO(IOReq);
  1043.                         }
  1044.                         FreeMem(SerUnit,sizeof(struct FSRUnit));
  1045.                 }
  1046.                 if (IOReq) {
  1047.                         if (IOReq->io_Device) CloseDevice(IOReq);
  1048.                         DeleteIORequest(IOReq);
  1049.                 }
  1050.                 if (IOPort) DeleteMsgPort(IOPort);
  1051.                 if (CmdPort) DeleteMsgPort(CmdPort);
  1052.                 goto quit;
  1053.         }
  1054.  
  1055.         quit:
  1056. #ifdef DEBUG
  1057.         if (DebugFile) Close(DebugFile);
  1058. #endif
  1059.         SocketBaseTags(SBTM_SETVAL(SBTC_LOGTAGPTR), NULL, TAG_END);
  1060.         if (TimePort) DeleteMsgPort(TimePort);
  1061.         if (Info) FreeMem(Info,sizeof(struct PasswdInfo));
  1062.         if (Inst) {
  1063.                 if (UserGroupBase) CloseLibrary(UserGroupBase);
  1064.                 if (SocketBase) CloseLibrary(SocketBase);
  1065.                 if (UtilityBase) CloseLibrary(UtilityBase);
  1066.                 if (DOSBase) CloseLibrary(DOSBase);
  1067.         }
  1068.         return 0;
  1069. }
  1070.  
  1071. void MyFPrintf(struct InstData *Inst,BPTR File,char *Fmt,...)
  1072. {
  1073.         VFPrintf(File,Fmt,(&Fmt)+1);
  1074. }
  1075.  
  1076. void mystrcat(char *Dest,char *Cat)
  1077. {
  1078.         memcpy(Dest+strlen(Dest),Cat,strlen(Cat)+1);
  1079. }
  1080.  
  1081. void mymovmem(char *From,char *To,int Len)
  1082. {
  1083.         int Cnt;
  1084.         if (From > To) {
  1085.                 for (Cnt=0;Cnt < Len;Cnt++) {
  1086.                         To[Cnt]=From[Cnt];
  1087.                 }
  1088.         } else if (From < To) {
  1089.                 for (Cnt=Len-1;Cnt >= 0;Cnt--) {
  1090.                         To[Cnt]=From[Cnt];
  1091.                 }
  1092.         }
  1093. }
  1094.  
  1095. struct Node *FindNode(struct List *List,struct Node *Node)
  1096. /* returns Node if Node is a member of list, NULL otherwise */
  1097. {
  1098.         struct Node *ChkNode;
  1099.  
  1100.         for (ChkNode=List->lh_Head;ChkNode->ln_Succ;ChkNode=ChkNode->ln_Succ) {
  1101.                 if (ChkNode==Node) return Node;
  1102.         }
  1103.         return NULL;
  1104. }
  1105.  
  1106. ULONG FakeBeginIO(void *IORequest)
  1107. {
  1108.         ((struct IORequest *)IORequest)->io_Flags &= ~IOF_QUICK; /* Quick IO not supported */
  1109.         ((struct IOExtSer *)IORequest)->io_Status &= ~(1<<0); /* clear abort bit */
  1110.         ((struct Node *)IORequest)->ln_Name=NULL; /* clear possible signature */
  1111.         PutMsg((struct MsgPort *)((struct FSRUnit *)((struct IORequest *)IORequest)->io_Unit)->fsru_UserData[0],IORequest);
  1112.         return 0;
  1113. }
  1114.  
  1115. ULONG FakeAbortIO(void *IORequest)
  1116. {
  1117.         struct IOExtSer *Ser;
  1118.  
  1119.         Ser=IORequest;
  1120.         Forbid();
  1121.                 Ser->io_Status |= (1<<0); /* Flag the request as aborted */
  1122.                 if (FindNode(((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[1],Ser) ||
  1123.                         FindNode(((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[2],Ser)) {
  1124.                                 /* This IORequest is waiting to be processed */
  1125.                                 Remove(Ser);
  1126.                                 Ser->IOSer.io_Error=IOERR_ABORTED;
  1127.                                 Ser->IOSer.io_Actual=0;
  1128.                                 ReplyMsg(Ser);
  1129.                 }
  1130.                 else {
  1131.                         /* This IORequest is currently being processed -- send a break */
  1132.                         Signal(((struct MsgPort *)((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[0])->mp_SigTask,SIGBREAKF_CTRL_C);
  1133.                 }
  1134.         Permit();
  1135.  
  1136.         return 0;
  1137. }
  1138.  
  1139. ULONG FakeOpen(void *IORequest)
  1140. {
  1141.         struct IOExtSer *Ser;
  1142.  
  1143.         Ser=IORequest;
  1144.         Forbid();
  1145.         ((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[3]=(void *) ((long)(((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[3])+1); /* Increment opencnt */
  1146.         Permit();
  1147.         Ser->IOSer.io_Error=0;
  1148.         Ser->io_CtlChar=SER_DEFAULT_CTLCHAR;
  1149.         Ser->io_RBufLen=(long)((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[4];
  1150.         Ser->io_ExtFlags=0;
  1151.         Ser->io_Baud=19200;
  1152.         Ser->io_BrkTime=250000;
  1153.         Ser->io_TermArray.TermArray0=0;
  1154.         Ser->io_TermArray.TermArray1=0;
  1155.         Ser->io_ReadLen=8;
  1156.         Ser->io_WriteLen=8;
  1157.         Ser->io_StopBits=1;
  1158.         Ser->io_Status=0;
  1159.         return 0;
  1160. }
  1161.  
  1162. ULONG FakeClose(void *IORequest)
  1163. {
  1164.         struct IOExtSer *Ser;
  1165.         struct Message *Msg;
  1166.  
  1167.         Ser=IORequest;
  1168.         Forbid();
  1169.  
  1170.         ((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[3]=(void *) ((long)(((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[3])-1); /* Decrement opencnt */
  1171.         Msg=AllocMem(sizeof(struct Message),MEMF_PUBLIC|MEMF_CLEAR);
  1172.         Msg->mn_Node.ln_Name=Signature;
  1173.         PutMsg((struct MsgPort *)((struct FSRUnit *)((struct IORequest *)IORequest)->io_Unit)->fsru_UserData[0],Msg);
  1174.  
  1175.         Permit();
  1176.         return 0;
  1177. }
  1178.  
  1179.  
  1180. struct DosPacket *PktFromMsg(struct Message *Msg)
  1181. {
  1182.         return (struct DosPacket *)Msg->mn_Node.ln_Name;
  1183. }
  1184.  
  1185. void PktFPuts(struct InstData *Inst,BPTR File,char *String)
  1186. {
  1187.         struct MsgPort *ReplyPort;
  1188.         struct DosPacket *Pkt;
  1189.  
  1190.         ReplyPort=CreateMsgPort();
  1191.         Pkt=AllocDosObject(DOS_STDPKT,NULL);
  1192.         if (!Pkt || !ReplyPort) return;
  1193.  
  1194.         Pkt->dp_Type=ACTION_WRITE;
  1195.         Pkt->dp_Arg1=((struct FileHandle *)BADDR(File))->fh_Arg1;
  1196.         Pkt->dp_Arg2=(LONG) String;
  1197.         Pkt->dp_Arg3=strlen(String);
  1198.         Pkt->dp_Port=ReplyPort;
  1199.         PutMsg(((struct FileHandle *)BADDR(File))->fh_Type,Pkt->dp_Link);
  1200.         WaitPort(ReplyPort);
  1201.         GetMsg(ReplyPort);
  1202.         DeleteMsgPort(ReplyPort);
  1203.         FreeDosObject(DOS_STDPKT,Pkt);
  1204. }
  1205.  
  1206. unsigned long GetInt(char *String,char **NewPtr)
  1207. {
  1208.         unsigned long Num=0;
  1209.         char *Junk;
  1210.         long Cnt;
  1211.         long BaseNum;
  1212.  
  1213.         if (!NewPtr) NewPtr=&Junk;
  1214.  
  1215.         for (*NewPtr=String;;(*NewPtr)++) {
  1216.  
  1217.                 if (**NewPtr < '0' || **NewPtr > '9') return Num;
  1218.  
  1219.                 /* AAARGH!! multiplication causes a lib call to be generated.
  1220.                    We can't use the library. Therefore we have to add */
  1221.                 /* Num=Num*10; */
  1222.                 for (BaseNum=Num,Cnt=0;Cnt < 9;Cnt++,Num+=BaseNum);
  1223.  
  1224.  
  1225.                 Num+=**NewPtr-'0';
  1226.         }
  1227.  
  1228. }
  1229.  
  1230.  
  1231. void SockPuts(struct InstData *Inst,int Sock,char *Buf)
  1232. {
  1233.         int BufPos=0;
  1234.         int BytesWritten;
  1235.  
  1236.         do {
  1237.                 BytesWritten=send(Sock,Buf+BufPos,strlen(Buf+BufPos),0);
  1238.                 if (BytesWritten > 0) BufPos+=BytesWritten;
  1239.         } while (Buf[BufPos]);
  1240. }
  1241.  
  1242. void SockRawWrite(struct InstData *Inst,int Sock,char *Buf,int Len)
  1243. {
  1244.         int BufPos=0;
  1245.         int BytesWritten;
  1246.  
  1247.         if (!Len) return;
  1248.  
  1249.         do {
  1250.                 BytesWritten=send(Sock,Buf+BufPos,Len-BufPos,0);
  1251.                 if (BytesWritten > 0) BufPos+=BytesWritten;
  1252.         } while (Len-BufPos);
  1253.  
  1254. }
  1255.  
  1256. void SockWrite(struct InstData *Inst,int Sock,char *Buf,int Len,int RawFlag)
  1257. {
  1258.         int Cnt;
  1259.         int BufPos=0;
  1260.         unsigned char iac2[2];
  1261.         char eol[2];
  1262.         char csi[2];
  1263.         iac2[0]=iac2[1]=IAC;
  1264.         eol[0]='\r';
  1265.         eol[1]='\n';
  1266.         csi[0]='\x1b';
  1267.         csi[1]='[';
  1268.  
  1269.  
  1270.         while (Len > BufPos) {
  1271.                 for (Cnt=BufPos;Cnt < Len;Cnt++) {
  1272.                         if (!RawFlag)
  1273.                                 if (Buf[Cnt]=='\r' || Buf[Cnt]=='\n') break;
  1274.                                 if (Buf[Cnt]=='\x9b') break;
  1275.                         if (Buf[Cnt]==IAC) {
  1276.                                 break;
  1277.                         }
  1278.                 }
  1279.                 SockRawWrite(Inst,Sock,Buf+BufPos,Cnt-BufPos);
  1280.                 BufPos=Cnt;
  1281.                 if (BufPos < Len && Buf[BufPos]==IAC) { /* If we got single IAC, send double IAC */
  1282.                         BufPos++;
  1283.                         SockRawWrite(Inst,Sock,iac2,2);
  1284.                 }
  1285.                 if (!RawFlag) {
  1286.                         if (BufPos < Len && Buf[BufPos]=='\r') {
  1287.                                 BufPos++;
  1288.                         }
  1289.                         if (BufPos < Len && Buf[BufPos]=='\n') {
  1290.                                 BufPos++;
  1291.                                 SockRawWrite(Inst,Sock,eol,2);
  1292.                         }
  1293.                         if (BufPos < Len && Buf[BufPos]=='\x9b') {
  1294.                                 BufPos++;
  1295.                                 SockRawWrite(Inst,Sock,csi,2);
  1296.                         }
  1297.                 }
  1298.         }
  1299. }
  1300.  
  1301. void ParseBuf3(struct InstData *Inst)
  1302. /* Parse 3 character remote request */
  1303. {
  1304.  
  1305. }
  1306.  
  1307. void ParseBuf2(struct InstData *Inst)
  1308. /* Parse 2 character remote-request */
  1309. {
  1310.  
  1311. }
  1312.  
  1313. void ParseBufSubNegotiate(struct InstData *Inst)
  1314. {
  1315.  
  1316. }
  1317.  
  1318. int RecvChar(struct InstData *Inst,int Sock,unsigned char *Loc,int RawMode)
  1319. {
  1320.         int GotLen;
  1321.         unsigned char Got,TrueGot;
  1322.         /*RawMode=TRUE;*/
  1323.         static unsigned char PrevChar;
  1324.  
  1325.         do {
  1326.  
  1327.                 GotLen=recv(Sock,&Got,1,0); /* Wait for a character */
  1328.                 if (GotLen==-1) {
  1329.                         if (Errno()==EINTR) continue;
  1330.                         else return -1;
  1331.                 } else if (GotLen==0) return 0;
  1332.  
  1333.                 TrueGot=Got;
  1334.                 if (!Inst->RecvBufPos && GotLen==1 && Got==0) GotLen=-1; /* Read again */
  1335.                 if (GotLen==1 && !RawMode && !Inst->RecvBufPos) {
  1336.                         /* These next few lines ignore incoming newlines and convert
  1337.                         incoming CRs into newlines   */
  1338.                         if (Got=='\n' && PrevChar=='\r') GotLen=-1; /* Read again. */
  1339.                         if (Got=='\r') Got='\n';
  1340.                 }
  1341.         } while (GotLen != 1);
  1342. /*      *Loc=Got;
  1343.         return 1; */
  1344.  
  1345.         if (Inst->RecvBufPos) {
  1346.                 Inst->RecvBuf[Inst->RecvBufPos]=Got;
  1347.                 Inst->RecvBufPos++;
  1348.                 switch (Inst->RecvBufPos) {
  1349.                         case 2:
  1350.                           switch(Inst->RecvBuf[1]) {
  1351.                                         case IAC:
  1352.                                           /* Just a single IAC */
  1353.                                                 *Loc=IAC;
  1354.                                                 return 1;
  1355.                                         break;
  1356.  
  1357.                                         case SB:
  1358.                                                 Inst->RecvBufFlags|=RBF_SUBNEGOTIATE;
  1359.                                                 return RecvChar(Inst,Sock,Loc,RawMode);
  1360.                                         break;
  1361.  
  1362.                                         case SE:
  1363.                                         Inst->RecvBufPos=0;
  1364.                                         Inst->RecvBufFlags &= ~RBF_SUBNEGOTIATE;
  1365.                                         return RecvChar(Inst,Sock,Loc,RawMode);
  1366.  
  1367.                                         case WILL:
  1368.                                         case WONT:
  1369.                                         case DO:
  1370.                                         case DONT:
  1371.                                         return RecvChar(Inst,Sock,Loc,RawMode);
  1372.                                         break;
  1373.  
  1374.                                         default:
  1375.                                         ParseBuf2(Inst);
  1376.                                         Inst->RecvBufPos=0;
  1377.                                         return RecvChar(Inst,Sock,Loc,RawMode);
  1378.                                 }
  1379.                         break;
  1380.  
  1381.                         default:
  1382.                                 if (Inst->RecvBufFlags & RBF_SUBNEGOTIATE) {
  1383.                                         if (Inst->RecvBufPos >= 2 && Inst->RecvBuf[Inst->RecvBufPos-2]==IAC && Inst->RecvBuf[Inst->RecvBufPos-1]!=IAC) {
  1384.                                                 /* End of subnegotiation */
  1385.                                                 Inst->RecvBuf[0]=IAC;
  1386.                                                 if ((Inst->RecvBuf[1]=Inst->RecvBuf[Inst->RecvBufPos-1])==SE) {
  1387.                                                         Inst->RecvBufFlags &= ~RBF_SUBNEGOTIATE;
  1388.                                                         Inst->RecvBufPos=0;
  1389.                                                         return RecvChar(Inst,Sock,Loc,RawMode);
  1390.                                                 }
  1391.                                                 Inst->RecvBufPos=2;
  1392.  
  1393.                                                 ParseBufSubNegotiate(Inst);
  1394.                                         }
  1395.  
  1396.                                         if (Inst->RecvBufPos >= 2 && Inst->RecvBuf[Inst->RecvBufPos-2]==IAC && Inst->RecvBuf[Inst->RecvBufPos-1]==IAC) {
  1397.                                                 /* We just got a double IAC in subnegotiation */
  1398.                                                 Inst->RecvBuf[Inst->RecvBufPos-2]=-1; /* We store IAC as a (int)-1 */
  1399.                                                 Inst->RecvBufPos--;
  1400.                                         }
  1401.                                         return RecvChar(Inst,Sock,Loc,RawMode);
  1402.                                 } else {
  1403.                                         if (Inst->RecvBuf[2]==IAC) {
  1404.                                                 /* Restart sequence */
  1405.                                                 Inst->RecvBuf[0]=IAC;
  1406.                                                 Inst->RecvBufPos=1;
  1407.                                                 return RecvChar(Inst,Sock,Loc,RawMode);
  1408.                                         } else {
  1409.                                           ParseBuf3(Inst);
  1410.                                                 Inst->RecvBufPos=0;
  1411.                                                 return RecvChar(Inst,Sock,Loc,RawMode);
  1412.                                         }
  1413.                                 }
  1414.                         break;
  1415.                 }
  1416.         }
  1417.         else {
  1418.                 if (Got==IAC) {
  1419.                         Inst->RecvBuf[0]=Got;
  1420.                         Inst->RecvBufPos=1;
  1421.                         return RecvChar(Inst,Sock,Loc,RawMode);
  1422.                 } else {
  1423.                         *Loc=Got;
  1424.                         PrevChar=TrueGot;
  1425.                         return 1;
  1426.                 }
  1427.         }
  1428.         return 1;
  1429.  
  1430. }
  1431.  
  1432.  
  1433. void SockGets(struct InstData *Inst,int Sock,char *Buf,int BufSize)
  1434. /* This function gets the next string until a CR
  1435. on the specified socket, and places it in buf. It
  1436. discards leading crs/lfs */
  1437. {
  1438.         int BufPos=0;
  1439.         int BytesRead;
  1440.         int FirstBytes=TRUE;
  1441.         Buf[0]='\0';
  1442.  
  1443.         do {
  1444.                 BytesRead=RecvChar(Inst,Sock,Buf+BufPos,FALSE);
  1445.                 if (BytesRead < 0) {
  1446.                         if (Errno()!=EINTR) {
  1447.                                 Buf[BufPos]='\0';
  1448.                                 return;
  1449.                         }
  1450.           }
  1451.                 else if (BytesRead==0) {
  1452.                         Buf[BufPos]='\0';
  1453.                         return;
  1454.                 }
  1455.                 else {
  1456.                         if ((Buf[BufPos]=='\r' || Buf[BufPos]=='\n') && FirstBytes) {
  1457.                                 Buf[BufPos]='\0';
  1458.                         } else {
  1459.                                 FirstBytes=FALSE;
  1460.                                 BufPos+=BytesRead;
  1461.                         }
  1462.                 }
  1463.         } while (Buf[BufPos-1] != '\r' && Buf[BufPos-1] != '\n' && BufPos < (BufSize-1));
  1464.         Buf[BufPos]='\0';
  1465. }
  1466.  
  1467. char *PullPasswdString(char **StringPtr)
  1468. {
  1469.         int Cnt;
  1470.         char *RetVal;
  1471.         char *CurPos;
  1472.  
  1473.         if (!StringPtr || !*StringPtr) return NULL;
  1474.  
  1475.         RetVal=*StringPtr;
  1476.  
  1477.         for (CurPos=RetVal;*CurPos != ',' && *CurPos != '\r' && *CurPos != '\n' && *CurPos;CurPos++);
  1478.         switch (*CurPos) {
  1479.                 case ',':
  1480.                 case '\r':
  1481.                 case '\n':
  1482.                         *CurPos='\0';
  1483.                         CurPos++;
  1484.                         *StringPtr=CurPos;
  1485.                 return RetVal;
  1486.  
  1487.                 case '\0':
  1488.                 *StringPtr=CurPos;
  1489.                 return RetVal;
  1490.         }
  1491. }
  1492.  
  1493. int mystrcmp(char *S1,char *S2)
  1494. {
  1495.         int Cnt;
  1496.         for (Cnt=0;S1[Cnt] && S2[Cnt];Cnt++) {
  1497.                 if (S1[Cnt] != S2[Cnt]) return !0;
  1498.         }
  1499.         if (S1[Cnt] != S2[Cnt]) return !0;
  1500.         return 0;
  1501. }
  1502.  
  1503. struct PasswdInfo *LookupPasswd(struct InstData *Inst,char *Login)
  1504. {
  1505.         BPTR File;
  1506.         char *LineBuf;
  1507.         char *BufPtr;
  1508.         char *PasswdPtr;
  1509.         char *LoginPtr;
  1510.         char *RealNamePtr;
  1511.         char *HomeDirPtr;
  1512.         char *CmdPtr;
  1513.         struct PasswdInfo *Info = NULL;
  1514.         struct passwd *result;
  1515.  
  1516.         if (result = getpwnam(Login)) {
  1517.                 if (Info=AllocMem(sizeof(struct PasswdInfo),MEMF_PUBLIC)) {
  1518.                         strcpy(Info->Login,result->pw_name);
  1519.                         strcpy(Info->Passwd,result->pw_passwd);
  1520.                         strcpy(Info->RealName,result->pw_gecos);
  1521.                         strcpy(Info->Command,result->pw_shell);
  1522.                 }
  1523.                 else
  1524.                         syslog(LOG_CRIT, "Couldn't allocate my info structure!");
  1525.         }
  1526.         else
  1527.                 syslog(LOG_INFO, "user %s is unknown here", Login);
  1528.  
  1529.         return Info;
  1530. }
  1531.  
  1532. void __asm PutMLSChar(register __d0 char Chr,register __a3 char **BufPtr)
  1533. {
  1534.         **BufPtr=Chr;
  1535.         (*BufPtr)++;
  1536. }
  1537.  
  1538. void MakeLongStr(char *StrBuf,unsigned long Num)
  1539. {
  1540.         RawDoFmt("%lu",&Num,PutMLSChar,&StrBuf);
  1541. }
  1542.  
  1543.  
  1544. struct Process *MyCreateNewProcTags(struct InstData *Inst,ULONG Tag1,...)
  1545. {
  1546.         return CreateNewProc((struct TagItem *)&Tag1);
  1547. }
  1548.  
  1549. void *MyAllocDosObjectTags(struct InstData *Inst,ULONG Type,ULONG Tag1,...)
  1550. {
  1551.         return AllocDosObject(Type,(struct TagItem *)&Tag1);
  1552. }
  1553. void MySystemTags(struct Library *DSBse,char *Cmd,ULONG Tag0,...)
  1554. {
  1555. #undef DOSBase
  1556. #define DOSBase DSBse
  1557.         SystemTagList(Cmd,(struct TagItem *)&Tag0);
  1558. #undef DOSBase
  1559. }
  1560.  
  1561. #define DOSBase DSBse
  1562. int __asm __saveds SubSubProc(register __a0 char *ArgString,register __d0 long Length)
  1563. {
  1564.         char StringBuf[1000];
  1565.         char *StringPtr;
  1566.         BPTR FH;
  1567.         struct Library *DSBse;
  1568.  
  1569.         DSBse=OpenLibrary("dos.library",36);
  1570.         if (!DSBse) return 0;
  1571.  
  1572.         FH=(BPTR)GetInt(ArgString,&StringPtr);
  1573.  
  1574. /*      if (IsInteractive(FH)) {
  1575.                 Write(FH,"Interactive\n",12);
  1576.         }*/
  1577.         strcpy(StringBuf,StringPtr);
  1578.     MySystemTags(DSBse,(StringBuf[0]) ? StringBuf : "execute S:remote-startup",
  1579.              SYS_Input,FH,
  1580.              SYS_Output,FH,
  1581.              NP_ConsoleTask,((struct FileHandle *)BADDR(FH))->fh_Type,
  1582.              NP_Cli,TRUE,
  1583.              TAG_END);
  1584.  
  1585.         Forbid();
  1586.         Close(FH);
  1587.         return 0;
  1588. }
  1589. #undef DOSBase
  1590.  
  1591.